package com.ksyun.campus.metaserver.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * Block metadata information
 */

/**
 * BlockInfo
 * ----------------------------------------
 * 作用：
 *   用于描述 minFS 中文件的一个数据块（Block）的元信息。
 *   每个文件在存储时会被切分成若干固定大小的块（blockSize 决定），
 *   每个块会被存储在多个 DataServer 上形成副本（Replica），
 *   以保证高可用和容错。
 *
 * 在文件读取和写入流程中：
 *   - metaServer 会返回该文件的所有 BlockInfo 列表
 *   - Client 根据这些信息去对应的 DataServer 读取或写入数据
 */

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BlockInfo {
    /**
     * fileId
     * ----------------------------------------
     * 所属文件的唯一 ID。
     * 注意：这里是内部的唯一标识（inode ID 或 UUID），
     *       而不是文件路径。
     * 作用：
     *   - 让 DataServer 能够根据 fileId + blkIdx 精确定位到数据块
     */
    private String fileId;
    /**
     * blkIdx
     * ----------------------------------------
     * 当前块在文件中的序号（从 0 开始）。
     * 例如：
     *   文件被切成 3 个块，则它们的 blkIdx 分别为 0、1、2。
     */

    private int blkIdx;
    /**
     * size
     * ----------------------------------------
     * 当前块实际存储的大小（字节数）。
     * 注意：
     *   - 除最后一个块外，通常 size == blockSize
     *   - 最后一个块可能小于 blockSize
     */
    private long size;
    /**
     * replicas
     * ----------------------------------------
     * 当前块的所有副本信息列表。
     * 每个副本存放在不同的 DataServer 上。
     * 至少会有一个 PRIMARY（主副本），
     * 其他为 REPLICA（从副本）。
     */
    private List<ReplicaInfo> replicas;
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ReplicaInfo {
        /**
         * dsId
         * ----------------------------------------
         * DataServer 的唯一 ID，用于在集群中标识节点。
         */
        private String dsId;
        /**
         * host
         * ----------------------------------------
         * DataServer 的主机名或 IP 地址。
         * Client 需要用它来建立网络连接。
         */
        private String host;
        /**
         * port
         * ----------------------------------------
         * DataServer 对外提供数据传输服务的端口号。
         */
        private int port;
        /**
         * role
         * ----------------------------------------
         * 当前副本的角色：
         *   PRIMARY → 主副本（负责写入 Pipeline 的起点）
         *   REPLICA → 从副本（从主副本接收数据）
         */
        private ReplicaRole role;
        
        public enum ReplicaRole {
            PRIMARY, REPLICA
        }
    }
}
